<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    //原型的作用
    // 节省内存空间、实现数据共享
</script>
<script>
    //构造函数、实例、（构造函数的）原型之间的关系
    function Person(name) {
        this.name = name;
    }
    //任何函数都有prototype属性，本身是一个对象
    //只有构造函数的prototype属性称为原型
    console.dir(Person);
    console.log(Person.prototype);

    //prototy中的属性和方法可以被实例化对象继承
    let zs = new Person('zs',)
    Person.prototype.age = 20
    console.log(zs.age);//20

    //任何对象都有constructor属性，实例化对象的constructor属性指向构造函数
    console.log(zs);
    console.log(zs.constructor);//f Person(){}

    //构造函数的原型的constructor属性指向构造函数自己
    console.log(Person.prototype.constructor);

    //实例化对象的__proto__属性指向构造函数的原型
    console.log(zs);
    console.log(zs.__proto__);
</script>
<script>
    function Person(name) {
        this.name = name;
    }
    //this指向  this指向被调用的地方
    Person.prototype.say = function () {
        console.log(this);
    }
    let ls = new Person('ls')

    //实例化对象调用原型中的方法，方法中的this指向实例化对象（实例对象调用）
    ls.say()//打印实例化对象ls

    //构造函数原型直接调用方法，this指向原型（构造函数原型调用）
    Person.prototype.say()
    console.log(Person.prototype);//结果一致
</script>
<script>
    //实例化对象的查找规则
    //先从自身对象中查找，没有找到在原型中查找，没有找到再从原型中的prototype中查找，依次向下
    function Person(name) {
        this.name = name;
    }
    Person.prototype.__proto__.age = 20
    let zw = new Person('zw')
    console.log(zw.age);
    //原型链最终指向null（最后一层的__proto__指向null）
    console.log(zw.__proto__);//指向zw的原型
    console.log(zw.__proto__.__proto__);
    console.log(zw.__proto__.__proto__.__proto__);//null
</script>

</html>